<?php

namespace Common\Service;
use \Think\Log;

class Wechat{

    //签名
    private $token = 'fengchi';

    //消息类型
    private $msgtype;

    //消息内容
    private $msgobj;

    //事件类型
    private $eventtype;

    //事件key值
    private $eventkey;

    #{服务号才可得到
    //AppId
    private $appid = "wx7639c41625861d06";
    //AppSecret
    private $secret = "4f55a01cc9504e495e4c68a2f2c6101f";
    #}
    
    private $_isvalid = false;
    
    public function __construct($isvalid = false){
        //$this->token = $token;
        $this->_isvalid = $isvalid;
    }
    
    /**
     *    执行程序入口
     */
    public function index(){
        if($this->_isvalid){
            $this->valid();
        }
        $this->getMsg();
        $this->responseMsg();
    }

    /**
     *  初次校验
     */
    private function valid(){
        $echoStr = $_GET["echostr"];

        if($this->checkSignature()){
            echo $echoStr;
            exit();
        }
    }

    /**
     *  创建自定义菜单
     */
    public function createMenu($menujson){

        $url = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token=".$this->getAccessToken();  
        $ch = curl_init($url);
        curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
        curl_setopt($ch, CURLOPT_POSTFIELDS,$menujson);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
        $info = curl_exec($ch);

        if (curl_errno($ch)) {
            echo 'Errno'.curl_error($ch);
        }

        curl_close($ch);
        var_dump($info);
    }


    /**
     *  删除自定义菜单
     */
    private function deleteMenu(){
        $url = "https://api.weixin.qq.com/cgi-bin/menu/delete?access_token=".$this->getAccessToken();
        $ch = curl_init($url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
        $info = curl_exec($ch);
        if (curl_errno($ch)) {
            echo 'Errno'.curl_error($ch);
        }
        curl_close($ch);
        var_dump($info);
    }

    /**
     *  获取消息
     */
    private function getMsg(){
        //验证消息的真实性
        /*if(!$this->checkSignature()){
            exit();
        }*/
        //接收消息
        $poststr = $GLOBALS["HTTP_RAW_POST_DATA"];
        if(!empty($poststr)){
            $this->msgobj = simplexml_load_string($poststr,'SimpleXMLElement',LIBXML_NOCDATA);
            $this->msgtype = strtolower($this->msgobj->MsgType);
        }
        else{
            $this->msgobj = null;
        }
    }

    /**
     *  回复消息
     */
    private function responseMsg(){
        log::write("222");
        switch ($this->msgtype) {
            case 'text':
                Log::write('测试日志信息');
                $data = $this->getData($this->msgobj->Content);
                if(empty($data) || !is_array($data)){
                    $content = "你在说什么，我不懂。";
                    $this->textMsg($content);//查询不到记录返回提示信息
                }
                else{
                    $this->newsMsg($data);
                }
                break;
            case 'event':
                $this->eventOpt();
                break;
            default:
                # code...
                break;
        }
    }

    /**
     *  回复文本消息
     */
    private function textMsg($content=''){
        $textxml = "<xml><ToUserName><![CDATA[{$this->msgobj->FromUserName}]]></ToUserName><FromUserName><![CDATA[{$this->msgobj->ToUserName}]]></FromUserName><CreateTime>".time()."</CreateTime><MsgType><![CDATA[text]]></MsgType><Content><![CDATA[%s]]></Content></xml>";
        
        //做搜索处理
        if(empty($content)){
            $content = "查询功能正在开发中...";
        }
        $resultstr = sprintf($textxml,$content);
        echo $resultstr;
    }

    /**
     *  回复图文消息
     */
    private function newsMsg($data){
        if(!is_array($data)){
            exit();
        }
        $newscount = (count($data) > 10)?10:count($data);
        $newsxml = "<xml><ToUserName><![CDATA[{$this->msgobj->FromUserName}]]></ToUserName><FromUserName><![CDATA[{$this->msgobj->ToUserName}]]></FromUserName><CreateTime>".time()."</CreateTime><MsgType><![CDATA[news]]></MsgType><ArticleCount>{$newscount}</ArticleCount><Articles>%s</Articles></xml>";
        $itemxml = "";
        foreach ($data as $key => $value) {
            $itemxml .= "<item>";
            $itemxml .= "<Title><![CDATA[{$value['title']}]]></Title><Description><![CDATA[{$value['summary']}]]></Description><PicUrl><![CDATA[{$value['picurl']}]]></PicUrl><Url><![CDATA[{$value['url']}]]></Url>";
            $itemxml .= "</item>";
        }
        $resultstr = sprintf($newsxml,$itemxml);
        echo $resultstr;
    }

    /**
     *  事件处理
     */
    private function eventOpt(){
        $this->eventtype = strtolower($this->msgobj->Event);
        switch ($this->eventtype) {
            case 'subscribe':
                //做用户绑定处理
                $openid = $this->msgobj->FromUserName; //用户openid                       
                $userInfo = $this->getUserInfoBase($openid);
                
                Log::write(json_encode($userInfo,JSON_UNESCAPED_UNICODE));
                //取关重新关注
                if(M("wx_user")->where(array("openid"=>"$openid"))->find()){
                    $arr= array(
                            'sub_time'   =>time(),
                            'sub_status'   => 1,
                            'nickname' => $userInfo->nickname,  
                            'headimg' => $userInfo->headimgurl
                       );
                    M("wx_user")->where(array("openid"=>"$openid"))->save($arr);
                }else{
                    $arr= array(
                            'sub_time'   =>time(),
                            'sub_status'   => 1,
                            'openid'   =>"$openid",
                            'nickname' => $userInfo->nickname,  
                            'headimg' => $userInfo->headimgurl
                       );
                    M("wx_user")->add($arr);
                }         
                
                $content = "您好，欢迎关注风驰驾考微信公众账号。";
                $this->textMsg($content);
                break;
            case 'unsubscribe':
                Log::write(777);
                //做用户取消绑定的处理
                $openid = $this->msgobj->FromUserName; //用户openid                
                $arr = [
                        'unsub_time'   =>time(),
                        'sub_status'   => 0,  
                       ];
                M("wx_user")->where(array("openid"=>"$openid"))->save($arr);
                break;
            case 'click':
                $this->menuClick();
                break;
            case 'scan':
                Log::write(999);
                $content = "888";
                $this->textMsg($content);
                break;
            case 'scancode_waitmsg':

                

                break;    
            default:
                # code...
                break;
        }
    }

    /**
     *  自定义菜单事件处理
     */
    private function menuClick(){
        $this->eventkey = $this->msgobj->EventKey;
        switch ($this->eventkey) {
            case 'V1001_NEW':
                $data = $this->getData();
                $this->newsMsg($data);
                break;

            case 'about_us':
                log::write("555");
                $this->textMsg('“风驰驾考”公司总部位于东莞市南城区，在全国各省设有市场推广团队，已开通广州、深圳、中山、佛山四大城市。致力于发展互联网学车模式，改革传统驾考培训弊端，是以用户学车体验为核心的专业，有效改善传统学车难，练车难，服务差等学车痛点，让学员尽享专业、品质、服务至上的学车体验！更多信息请咨询客服热线：0769-33603678');
                break;

            default:
                # code...
                break;
        }
    }

    /**
     *    获取本地数据
     */
    private function getData($key='ruiblog'){
        $data = $key;
        //写你自己相关的程序
        return $data;
    }
    
    /**
     *  校验签名
     */
    private function checkSignature(){
        $signature = $_GET["signature"];
        $timestamp = $_GET["timestamp"];
        $nonce = $_GET["nonce"];    
                
        $token = $this->token;
        $tmpArr = array($token, $timestamp, $nonce);
        sort($tmpArr);
        $tmpStr = implode( $tmpArr );
        $tmpStr = sha1( $tmpStr );
        
        return ($tmpStr == $signature)?true:false;
    }

    /**
     *  获取access token
     */
    public function getAccessToken(){
        //将token缓存起来
        /*if(S('_token_')){
            $token = S('_token_');
        }else{*/
            $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=$this->appid&secret=$this->secret";
            $atjson=file_get_contents($url);
            $result=json_decode($atjson,true);
            if(!isset($result['access_token'])){
                var_dump($result);
                exit();
            }

            $token = $result["access_token"];
        //     S('_token_',$token,array('type'=>'file','expire'=>7000));
        // }
        return $token;
    }

    /**
     *  获取jsapi_ticket
     */
    private function getJsTicket(){

        //将ticket缓存起来
        if(S('_ticket_')){
            $ticket = S('_ticket_');
        }else{

            $accessToken = $this->getAccessToken();    
            $url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=jsapi&access_token=$accessToken";
            $res = json_decode(file_get_contents($url));

            if(!isset($res->ticket)){
                exit( '获取js_ticket失败！' );
            }

            $ticket = $res->ticket;
            S('_ticket_',$ticket,array('type'=>'file','expire'=>7000));
        }
        return $ticket;
    }

    /**
     *  jssdk所需数据
     */
    public function getSignPackage() {

        $jsapiTicket = $this->getJsTicket();

        //注意 URL 一定要动态获取，不能 hardcode.
        $protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' || $_SERVER['SERVER_PORT'] == 443) ? "https://" : "http://";
        $url = "$protocol$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";

        $timestamp = time();
        $nonceStr = $this->createNonceStr();

        // 这里参数的顺序要按照 key 值 ASCII 码升序排序
        $string = "jsapi_ticket=$jsapiTicket&noncestr=$nonceStr&timestamp=$timestamp&url=$url";

        $signature = sha1($string);
        $signPackage = array(
            "appId" => $this->appid,
            "nonceStr" => $nonceStr,
            "timestamp" => $timestamp,
            "url" => $url,
            "signature" => $signature,
            "rawString" => $string
        );
        return $signPackage;
    }

    private function createNonceStr($length = 16) {
        $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        $str = "";
        for ($i = 0; $i < $length; $i++) {
            $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
        }
        return $str;
    }

    /**
     *  oauth2授权
     */
    public function getOpenidByOauth($usertype = "snsapi_userinfo"){

        //通过code获得openid
        if(isset($_GET['code'])){
            $code = $_GET['code'];
            $response = 'https://api.weixin.qq.com/sns/oauth2/access_token?appid='.$this->appid.'&secret='.$this->secret.'&code='.$code.'&grant_type=authorization_code';

            $res = file_get_contents($response);
            $res = json_decode($res);
            //code码未失效，失效后errcode返回40163(code码五分钟有效，并且仅能使用一次)
            if(!isset($res->errcode)){
                Log::write('0000000000000000---'.json_encode($res));
                //return $res->openid;
                return $res;
            }
        }

        //不存在code或者code失效，都进行下面跳转
        $baseUrl = urlencode('http://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']);
        $url = $this->getOauthUrlForCode($baseUrl,$usertype);
        Log::write('11111111111111---'.$url);
        Header("Location: $url");
        exit();
    }

    /**
     * 构造获取code的url连接
     */
    private function getOauthUrlForCode($redirectUrl,$usertype){
        $urlObj["appid"] = $this->appid;
        $urlObj["redirect_uri"] = "$redirectUrl";
        $urlObj["response_type"] = "code";
        $urlObj["scope"] = $usertype;
        $urlObj["state"] = "STATE"."#wechat_redirect";
        $bizString = $this->ToUrlParams($urlObj);
        return "https://open.weixin.qq.com/connect/oauth2/authorize?".$bizString;
    }

    /**
     * 拼接签名字符串
     */
    private function ToUrlParams($urlObj){

        $buff = "";
        foreach ($urlObj as $k => $v)
        {
            if($k != "sign"){
                $buff .= $k . "=" . $v . "&";
            }
        }

        $buff = trim($buff, "&");
        return $buff;
    }


    /**
     * 网页授权后获取用户的信息
     * 注意一点的就是，这里的access_token是用户授权产生的，而不是普通的那个access_token
     */
    public function getUserInfo($openid,$access_token){
        $url = "https://api.weixin.qq.com/sns/userinfo?access_token=".$access_token."&openid=".$openid."&lang=zh_CN";
        $userInfo = json_decode(file_get_contents($url));
        return $userInfo;
    }

    /**
     * 关注公众号后获取用户的信息
     */
    public function getUserInfoBase($openid){
        $url = 'https://api.weixin.qq.com/cgi-bin/user/info?access_token='.$this->getAccessToken().'&openid='.$openid.'&lang=zh_CN';
        $userInfo = json_decode(file_get_contents($url));
        return $userInfo;
    }

    //curl post获取消息
    public function curl_post($url="", $data="")
    {
        
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);//设定为不验证证书和host
        curl_setopt ( $ch, CURLOPT_URL, $url);
        curl_setopt ( $ch, CURLOPT_POST, 1 );
        curl_setopt ( $ch, CURLOPT_HEADER, 0 );
        curl_setopt ( $ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt ( $ch, CURLOPT_POSTFIELDS, $data );
        $res = json_decode(curl_exec($ch));
        return $res;
    }
}

?>